package com.open.capacity.finance.config;

import com.open.capacity.finance.entity.AuditModel;
import com.open.capacity.finance.entity.SpringScheduledCron;
import com.open.capacity.finance.service.AbstractAuditMakeResultFactory;
import com.open.capacity.finance.service.AuditModelService;
import com.open.capacity.finance.service.SpringScheduledCronService;
import com.open.capacity.finance.task.AuditModelWarnTask;
import com.open.capacity.finance.task.ScheduledOfTask;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * @author ftquan
 * @date 2019/5/10
 */
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {

    @Autowired
    private ApplicationContext context;

    @Autowired
    private SpringScheduledCronService cronService;

    @Autowired
    private AuditModelService modelService;

    private static final String EXCUTEAUDITCLASSPATHNAME = "com.open.capacity.finance.service.impl.AuditModelActuator%sServiceImpl";


    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        Map<String, Object> params = new HashMap<>();
        for (SpringScheduledCron springScheduledCron : cronService.findAll(params)) {
            Class<?> clazz;
            Object task;
            try {
                clazz = Class.forName(springScheduledCron.getCronKey());
                task = context.getBean(clazz);

                //动态注入属性
                ((ScheduledOfTask) task).setCronId(springScheduledCron.getCronId());

            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException("spring_scheduled_cron表数据" + springScheduledCron.getCronKey() + "有误", e);
            } catch (BeansException e) {
                throw new IllegalArgumentException(springScheduledCron.getCronKey() + "未纳入到spring管理", e);
            }
            Assert.isAssignable(ScheduledOfTask.class, task.getClass(), "定时任务类必须实现ScheduledOfTask接口");
            // 可以通过改变数据库数据进而实现动态改变执行周期
            taskRegistrar.addTriggerTask(((Runnable) task),
                    triggerContext -> {
                        String cronExpression = cronService.findById(springScheduledCron.getCronId()).getCronExpression();
                        return new CronTrigger(cronExpression).nextExecutionTime(triggerContext);
                    }
            );
        }

        for (AuditModel model : modelService.findAll(params)) {
            Class<?> clazz;

            Object task;
            try {
                clazz = Class.forName("com.open.capacity.finance.task.AuditModelWarnTask");
                task = context.getBean("AuditModel" + model.getCode() + "WarnTask", clazz);

                //动态注入属性
                ((AuditModelWarnTask) task).MODELID = model.getCode();
                ((AuditModelWarnTask) task).service = (AbstractAuditMakeResultFactory) context.getBean(Class.forName(String.format(EXCUTEAUDITCLASSPATHNAME, model.getCode())));

                Assert.isAssignable(ScheduledOfTask.class, task.getClass(), "定时任务类必须实现ScheduledOfTask接口");
                // 可以通过改变数据库数据进而实现动态改变执行周期
                taskRegistrar.addTriggerTask(((Runnable) task),
                        triggerContext -> {
                            String cronExpression = model.getCronExpression();
                            return new CronTrigger(cronExpression).nextExecutionTime(triggerContext);
                        }
                );

            } catch (ClassNotFoundException e) {
                //throw new IllegalArgumentException(model.getCode() + "AuditModel1WarnTask 有误", e);
            } catch (BeansException e) {
                //throw new IllegalArgumentException(model.getCode() + "AuditModel1WarnTask未纳入到spring管理", e);
            }
        }


    }
}
